import { WinstonModule } from 'nest-winston';
import { utilities as nestWinstonModuleUtilities } from 'nest-winston';
import * as winston from 'winston';
import { LoggerService, LogLevel } from '@nestjs/common';
import 'winston-daily-rotate-file';
import { appConfig } from '../config/app.config';
const pkg = require('../../package.json');
const MySQLTransport = require('winston-mysql-leaper');
const { Sequelize } = require('sequelize');
import * as schedule from 'node-schedule';

const customFormat = winston.format.combine(
    winston.format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss' }),
    winston.format.splat(),
    winston.format.printf((i) => `${[i.timestamp]} [${i.level}]: ${i.message}`),
);

/**
 * 日志存储库配置
 */
export const logsDbConfig = {
    host: process.env.logs_host || '127.0.0.1',
    user: process.env.logs_user || 'root',
    password: process.env.logs_password || 'root',
    port: Number(process.env.logs_port) || 3306,
};

const defaultOptions = {
    format: customFormat,
    datePattern: 'YYYY-MM-DD',
    maxSize: appConfig.logs.max_size || '2g',
    maxFiles: appConfig.logs.max_files || '7d',
    dirname: appConfig.logs.dirname || './logs/',
};

//打印格式化
const print_format = new winston.transports.Console({
    format: winston.format.combine(
        winston.format.timestamp(),
        winston.format.ms(),
        nestWinstonModuleUtilities.format.nestLike(pkg.name || 'test_app', {
            colors: true,
            prettyPrint: true,
        }),
    ),
    level: 'debug',
});

// 标准输出日志持久化
const presis_info = new winston.transports.DailyRotateFile({
    filename: 'logs/info-%DATE%.log',
    level: 'info',
    ...defaultOptions,
});

// 错误日志持久化
const presis_err = new winston.transports.DailyRotateFile({
    filename: 'logs/error-%DATE%.log',
    level: 'error',
    ...defaultOptions,
});

const logsTableName = pkg.name || 'nest_template';
const transports = [print_format, presis_info, presis_err];

export class Logger implements LoggerService {
    private logger: LoggerService;

    constructor() {
        this.logger = WinstonModule.createLogger({
            format: customFormat,
            transports: transports,
        });
    }
    log(message: any, ...optionalParams: any[]) {
        this.logger.log(message, ...optionalParams);
    }
    error(message: any, ...optionalParams: any[]) {
        this.logger.error(message, ...optionalParams);
    }
    warn(message: any, ...optionalParams: any[]) {
        this.logger.warn(message, ...optionalParams);
    }
    debug?(message: any, ...optionalParams: any[]) {
        this.logger.debug(message, ...optionalParams);
    }
    verbose?(message: any, ...optionalParams: any[]) {
        this.logger.verbose(message, ...optionalParams);
    }
    setLogLevels?(levels: LogLevel[]) {
        this.logger.setLogLevels(levels);
    }
}

if (logsDbConfig.host && logsDbConfig.password && logsDbConfig.port && logsDbConfig.user) {
    if (process.env.NODE_ENV == 'production') {
        transports.push(
            new MySQLTransport({
                ...logsDbConfig,
                database: 'web_logs',
                table: logsTableName,
            }),
        );
    }
}

export async function initLogsDb() {
    if (logsDbConfig.host && logsDbConfig.password && logsDbConfig.port && logsDbConfig.user) {
        // init clean task
        if (process.env.NODE_ENV == 'production') {
            const seq = new Sequelize({
                dialect: 'mysql',
                ...logsDbConfig,
                username: logsDbConfig.user,
            });

            // 初始化数据库结构
            await seq.query(`CREATE DATABASE  IF NOT EXISTS web_logs  DEFAULT CHARACTER SET = 'utf8mb4'`);
            await seq.query(`
            CREATE TABLE IF NOT EXISTS web_logs.${logsTableName} (
                \`id\` int(11) NOT NULL AUTO_INCREMENT, \`level\` varchar(16) NOT NULL, \`message\` varchar(2048) NOT NULL, \`meta\` varchar(2048) NOT NULL, \`timestamp\` datetime NOT NULL, PRIMARY KEY (\`id\`), KEY \`level\` (\`timestamp\`,\`level\`)
            ) ENGINE = InnoDB AUTO_INCREMENT = 134 DEFAULT CHARSET = utf8mb4
        `);

            // const logger = new Logger();
            const job = schedule.scheduleJob('0 0 1/ * * *', async function () {
                const res = await seq.query(
                    `DELETE FROM web_logs.${logsTableName} WHERE timestamp < DATE_SUB(NOW(), INTERVAL 7 DAY);`,
                );
                // logger.log(`清楚任务执行: 清除日志条数${res[0].affectedRows}`);
            });
        }
    }
}
